/*##############################################################################
# pslint - utility to pre-check personal statements for common mistakes        #
# and wasted space before input onto a form                                    #
#                                                                              #
#                                pslint.cpp                                    #
#                                                                              #
# inspired by Void Linux's xlint (from xtools)                                 #
#                                                                              #
# (C) 2016 William Obiri-Danso                                                 #
#                                                                              #
# Licensed under the Apache License, Version 2.0 (the "License");              #
# you may not use this file except in compliance with the License.             #
# You may obtain a copy of the License at                                      #
#                                                                              #
#     http://www.apache.org/licenses/LICENSE-2.0                               #
#                                                                              #
# Unless required by applicable law or agreed to in writing, software          #
# distributed under the License is distributed on an "AS IS" BASIS,            #
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.     #
# See the License for the specific language governing permissions and          #
# limitations under the License.                                               #
##############################################################################*/ 

#include <iostream>
#include <fstream>
#include <string>
#include <cstdlib>

// Preprocessor constants
#define VERSION 3

// TODO: Do not hard code these (or have an option to not hardcode)
#define MAX_COLS 67 // from 74. Whyyyyyyy
#define MAX_LINES 47

#define MIN_CHARS 1000
#define MAX_CHARS 4000

void welcome() {
    std::cout << "pslint-"<<VERSION<<" compiled on " <<__DATE__<< " at " <<__TIME__<< std::endl;
    
    std::cout << std::endl;
    
    std::cout << "(C) 2016 William Obiri-Danso" << std::endl;
    std::cout << "Licenced under Apache 2.0" << std::endl;
    
    std::cout << std::endl;
    
    std::cout << "*** WARNING: PLEASE UNDERSTAND: ***" << std::endl;
    std::cout << "* That this utility does NOT check for spelling mistakes" << std::endl;
    std::cout << "* That it is NOT a replacement for a personal tutor or proofreader" << std::endl;
    
    std::cout << std::endl;
}

int checkStats(int numChars, int numLines) {
    std::string warningChars = "[!!!]";
    std::string okChars = "[OK!]";
    bool error = false;
    
    std::cout << "-----------------------------------------------" << std::endl;
    std::cout << "                     Results                   " << std::endl;
    std::cout << "-----------------------------------------------" << std::endl;
    if (numLines > MAX_LINES) {
         std::cout << "Number of lines: "<<numLines<<"                     "<<warningChars<< std::endl;
         std::cout << "Limit = "<<MAX_LINES<<"Current = "<<numLines - MAX_LINES<< std::endl;
         error = true;
    } else {
        std::cout << "Number of lines: "<<numLines<<"                       "<<okChars<< std::endl;
    }
    
    if (numChars > MAX_CHARS) {
         std::cout << "Number of characters: "<<numChars<<"               "<<warningChars<< std::endl;
         std::cout << "Limit = "<<MAX_CHARS<<"Current = "<<numChars - MAX_CHARS<< std::endl;
         error = true;
    } else if (numChars < MIN_CHARS) {
         std::cout << "Number of characters: "<<numChars<<"               "<<warningChars<< std::endl;
         std::cout << "Limit = "<<MIN_CHARS<<"Current = "<<MIN_CHARS - numChars<< std::endl;
         error = true;
    } else {
        std::cout << "Number of characters: "<<numChars<<"                "<<okChars<< std::endl;
    }
    std::cout << "-----------------------------------------------" << std::endl;
    
    if (error) {
        return 1;
    } else {
        return 0;
    } 
}

int genStats(std::string path) {
    
    std::ifstream input(path);
    
    int numChars = 0;
    int numLines = 0;
    
    while (input) {
        std::string temp;
        std::getline(input, temp);
        numChars += temp.length();
    }
    
    // Count the number of lines by dividing by the col count. This compensates
    // for different text processors.
    numLines = numChars / MAX_COLS; 
    
    // pass by value to check stats.
    int status = checkStats(numChars, numLines);
    return status;
}

int main(int argc, char **argv) {
    
    welcome();
    if (argc == 1) {
        std::cerr << "!!! Error 1: No file input for checking !!!" << std::endl;
        exit(1);
    } else {
        // For now, assume argv ONLY contains the file path
        std::string path = std::string(argv[1]);
    
        std::ifstream input(path);
    
        if (!input) {
            std::cerr << "Error 2: Could not open \""<<path<<"\" for reading!!!"<< std::endl;
            exit(2);
        }
    
        std::cout << "*** File OK! ***" << std::endl;
        
        // Run genStats to check file.
        if (genStats(path)) {
            std::cerr << "!!! Error 3: The text does not conform to requirements !!!" << std::endl;
            std::cerr << "!!! Look above this message to see why !!!" << std::endl;
            exit(3);
        } else {
            std::cout << std::endl;
            std::cout << "*** No (format) errors found! :) ***" << std::endl;
            return 0;
        }  
        
    }
}
